<template>
	<view :style="{'margin-top':marginTop+'rpx'}">
		<view v-if="loading">
			<block v-for="(item, index) in elements" :key="index">
				<!-- 横向并列布局 -->
				<view class="ls_skeleton-group" v-if="item.type=='flex'">
					<view :class="[inner.clas, index2>0?'ls_ml':'']" v-for="(inner, index2) in item.children" :key="index2">
						<view :class="[el.clas, el.clas=='ls_circle'?'':style, animateClass]" v-for="(el, index3) in inner.eles" :key="index3" ref="skeleton"></view>
					</view>
				</view>
				<!-- 扩展模板：新闻资讯模板 -->
				<!-- ps 自定义扩展说明： -->
				<!-- 如果你需要自定义模板，可以参照这个news的写法，增加一个skeleton配置类型，编写布局和样式就可以了 -->
				<!-- 注意事项：为了保证骨架效果和动态效果的一致，扩展时，在你希望实际展示在页面中的元素上加上 :class="[style, animateClass]" 和 ref="skeleton" -->
				<view class="ls_skeleton-group" v-else-if="item.type=='news'">
					<view class="ls_news_img" :class="[style, animateClass]" ref="skeleton"></view>
					<view class="ls_news">
						<view class="ls_line" :class="[style, animateClass]" ref="skeleton"></view>
						<view class="ls_news_user" :class="[style, animateClass]" ref="skeleton"></view>
						<view class="ls_news_time" :class="[style, animateClass]" ref="skeleton"></view>
					</view>
				</view>
				<!-- 扩展首页推荐模块 -->
				<view class="recommend" v-else-if="item.type=='recommend'">
					<view class="item" v-for="(inner,index2) in 4" :key="index2">
						<view class="img" :class="[style, animateClass]" ref="skeleton"></view>
						<view class="title" :class="[style, animateClass]" ref="skeleton"></view>
					</view>
				</view>
				<!-- 扩展tab+文档信息列表的骨架 -->
				<view class="skeleton-tabs" v-else-if="item.type=='list'">
					<view class="tab-bar" :class="[style, animateClass]" ref="skeleton" v-if="item.show_type==1"></view>
					<view class="tab-list">
						<view class="item" v-for="(inner,index2) in 10" :key="index2">
							<view class="format" :class="[style, animateClass]" ref="skeleton"></view>
							<view class="content">
								<view class="title" :class="[style, animateClass]" ref="skeleton"></view>
								<view class="row row1" :class="[style, animateClass]" ref="skeleton"></view>
								<view class="row" :class="[style, animateClass]" ref="skeleton" v-if="item.show_type!=3"></view>
							</view>
						</view>
					</view>
				</view>
				<!-- 扩展无tab的文档信息列表的骨架 -->
				<view class="skeleton-tabs" v-else-if="item.type=='docs'">
					<view class="tab-list">
						<view class="item" v-for="(inner,index2) in 10" :key="index2">
							<view class="format" :class="[style, animateClass]" ref="skeleton"></view>
							<view class="content">
								<view class="title" :class="[style, animateClass]" ref="skeleton"></view>
								<view class="row" :class="[style, animateClass]" ref="skeleton"></view>
							</view>
						</view>
					</view>
				</view>
				<!-- 扩展tab+资金明细处的骨架 -->
				<view class="skeleton-balance" v-else-if="item.type=='balance'">
					<view class="tab-bar" :class="[style, animateClass]" ref="skeleton" v-if="item.show_type==1"></view>
					<view class="tab-list">
						<view class="item" v-for="(inner,index2) in 15" :key="index2">
							<view class="t" :class="[style, animateClass]" ref="skeleton"></view>
							<view class="b" :class="[style, animateClass]" ref="skeleton"></view>
						</view>
					</view>
				</view>
				<!-- 扩展，显示页面整体加载效果 -->
				<view class="skeleton-loading" v-else-if="item.type=='loading'">
					<uni-transition :show="true" :duration="150">
						<view class="inner" :style="{height: winHeight+'px'}" :class="[style, animateClass]" ref="skeleton">
							<view class="icon">
								<doc-loading :size="34"></doc-loading>
								<text class="text">加载中...</text>
							</view>
						</view>
					</uni-transition>
				</view>
				<!-- 扩展分类页面 -->
				<view class="skeleton-classify" v-else-if="item.type=='classify'">
					<uni-transition class="uni-transition" :show="true" :duration="100">
						<view class="parent" :class="[style, animateClass]" ref="skeleton"></view>
						<view class="child">
							<doc-list :pullRefresh="false" :bounce="false">
								<cell class="cell">
									<view class="item" v-for="(inner,index2) in 50" :key="index2" :class="[style, animateClass]" ref="skeleton"></view>
								</cell>
							</doc-list>
						</view>
					</uni-transition>
				</view>
				<!-- 扩展消息界面 -->
				<view class="skeleton-message" v-else-if="item.type=='message'">
					<uni-transition class="uni-transition" :show="true" :duration="100">
						<view class="hd">
							<template v-for="item in 3">
								<view class="item" :key="item" :class="[style, animateClass]" ref="skeleton"></view>
							</template>
						</view>
						<view class="bd">
							<template v-for="item in 10">
								<view class="item" :key="item">
									<view class="head" :class="[style, animateClass]" ref="skeleton"></view>
									<view class="list">
										<view class="t">
											<text class="name" :class="[style, animateClass]" ref="skeleton"></text>
											<text class="time" :class="[style, animateClass]" ref="skeleton"></text>
										</view>
										<view class="b">
											<text class="text" :class="[style, animateClass]" ref="skeleton"></text>
										</view>
									</view>
								</view>
							</template>
						</view>
					</uni-transition>
				</view>
				<!-- 垂直高度站位 -->
				<view :style="{height: item.height+'rpx'}" v-else-if="item.type=='space'"></view>
				<!-- 其他基本单位  line  card circle 等 -->
				<view :class="[item.clas, item.clas=='ls_circle'?'':style, animateClass]" v-else ref="skeleton"></view>
			</block>
		</view>
		<view v-else style="flex: 1;width: 750rpx;">
			<slot />
		</view>
	</view>
</template>
<script>
	import {
		getElCountsAndLayout,
		getElCounts
	} from './util';
	// #ifdef APP-NVUE
	const animationActuator = weex.requireModule('animation');
	let interval;
	// #endif
	/**
	 * ls-skeleton 骨架屏
	 * @description 可自定义内容的骨架屏
	 * @property {Boolean} loading 是否显示骨架（默认：否）
	 * @property {Boolean} round 是否圆角骨架风格（默认：否）
	 * @property {Boolean} animate 是否开启动画效果（默认：是）
	 * @property {Array} skeleton 骨架内容 （段落：line|line-sm|line-lg| 卡片：card|card-sm|card-lg| 圆：circle|circle-sm|circle-lg 正方形：square|square-sm|square-lg）个数标识符*  横向并列连接标识符+
	 * @example 
	 * <ls-skeleton :skeleton="skeleton" :loading="loading">
	 * 	<view>好的，页面加载完了</view>
	 * </ls-skeleton>
	 */
	export default {
		name: 'ls-skeleton',
		props: {
			// 是否显示骨架
			loading: {
				type: Boolean,
				default: true
			},
			// 是否圆角骨架风格
			round: {
				type: Boolean,
				default: false
			},
			// 骨架内容 特殊符号说明 [*代表个数 例如：line*3 意思是3个行] [+代表横向并列排列连接  例如：circ+line 意思是左侧一个圆右侧一个行] [纯数字 代表垂直间隔 例如：40 代表40前后的两个元素之间有40rpx高度的间隔]
			skeleton: {
				type: Array,
				default: () => []
			},
			// 是否开启动画效果
			animate: {
				type: Boolean,
				default: true
			},
			// 整体偏移距离
			marginTop: {
				type: [Number],
				default: 0
			}
		},
		data() {
			return {
				elements: []
			}
		},
		computed: {
			animateClass() {
				return this.animate ? 'ls_animation' : 'ls_static';
			},
			style() {
				if (this.round) {
					return 'ls_round';
				}
				return 'ls_radius';
			},
			winHeight() {
				return uni.getSystemInfoSync().windowHeight;
			}
		},
		watch: {
			// 开始loading时，加载动画
			loading(val) {
				// #ifdef APP-NVUE
				if (val && this.animate) {
					this.createAnimation();
				}
				// #endif
			}
		},
		created() {
			this.init();
			// #ifdef APP-NVUE
			if (this.loading && this.animate) {
				setTimeout(() => {
					this.createAnimation();
				}, 40);
			}
			// #endif
		},
		methods: {
			init() {
				let elements = [];
				let elClass;
				this.skeleton.forEach(el => {
					if (typeof(el) === 'string') {
						if (el.indexOf("+") > -1) {
							let group = el.split("+");
							let children = [];
							group.forEach(els => {
								children.push(getElCountsAndLayout(els));
							});
							elements.push({
								type: 'flex',
								children: children
							});
						} else if (el === 'recommend') {
							elements.push({
								type: 'recommend',
								height: el
							});
						} else if (el.indexOf("list") > -1 && el.indexOf("-") > -1) {
							// show_type:1-全部显示 2-不显示tab,下面的全部显示 3-tab不显示,title下面的只显示一行
							let show_type = el.split("-")[1];
							elements.push({
								type: 'list',
								show_type: show_type
							});
						} else if (el.indexOf("balance") > -1 && el.indexOf("-") > -1) {
							// show_type:1-全部显示 2-不显示tab
							let show_type = el.split("-")[1];
							elements.push({
								type: 'balance',
								show_type: show_type
							});
						} else {
							elClass = getElCounts(el);
							elements = elements.concat(elClass);
						}
					} else if (typeof(el) === 'number') {
						elements.push({
							type: 'space',
							height: el
						});
					} else {
						console.warn("[ls-skeleton]: 参数格式包含了不符合规范的内容");
					}
				});
				this.elements = [...elements];
			},
			createAnimation() {
				let background = '#e6e6e6';
				clearInterval(interval);
				interval = setInterval(() => {
					background = background === '#e6e6e6' ? '#d3d3d3' : '#e6e6e6';
					this.executeAnimation(background);
				}, 1000);
			},
			executeAnimation(background) {
				// loading结束之后，移除计时器，动画不再执行
				if (!this.loading) {
					clearInterval(interval);
					return;
				}
				this.$refs.skeleton.forEach(item => {
					animationActuator.transition(item, {
						styles: {
							"backgroundColor": background,
						},
						duration: 800, //ms  
						timingFunction: 'linear'
					});
				})
			},
		}
	}
</script>
<style scoped lang="scss">
	@import url("css/index.css");

	/* 扩展模板recommend样式 */
	.recommend {
		flex-direction: row;
		align-items: center;
		padding: 0 18rpx;
		background-color: #fff;

		.item {
			width: 146rpx;
			height: 336rpx;
			margin: 0 16rpx;
			justify-content: center;

			.img {
				height: 204rpx;
			}

			.title {
				height: 60rpx;
				margin: 20rpx 0 0;
			}
		}
	}

	/* 扩展tab+文档信息列表的骨架 */
	.skeleton-tabs {
		.tab-bar {
			width: 750rpx;
			height: 100rpx;
		}

		.tab-list {
			.item {
				flex-direction: row;
				padding: 20rpx 0;
				margin: 0 32rpx;

				.format {
					width: 46rpx;
				}

				.content {
					margin: 0 0 0 24rpx;

					.title {
						width: 624rpx;
						height: 80rpx;
						margin: 0 0 26rpx 0;
					}

					.row {
						width: 624rpx;
						height: 36rpx;
					}

					.row1 {
						margin: 0 0 10rpx 0;
					}
				}
			}
		}
	}

	/*扩展tab+资金明细处的骨架*/
	.skeleton-balance {
		.tab-bar {
			width: 750rpx;
			height: 100rpx;
		}

		.tab-list {
			.item {
				margin: 0 34rpx;
				padding: 20rpx 0;

				.t {
					width: 682rpx;
					height: 40rpx;
					margin: 0 0 16rpx 0;
				}

				.b {
					width: 682rpx;
					height: 40rpx;
				}
			}
		}
	}

	/*扩展，显示页面整体加载效果 */
	.skeleton-loading {
		background-color: #F2F5F9;

		.inner {
			flex-direction: row;
			align-items: center;
			justify-content: center;

			.icon {
				flex-direction: row;
				align-items: center;
				margin: -200rpx 0 0;

				.text {
					margin: 0 0 0 10rpx;
					font-size: 32rpx;
					color: #999;
				}
			}
		}
	}

	.skeleton-classify {
		position: fixed;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;

		.uni-transition {
			flex-direction: row;
		}

		.parent {
			width: 200rpx;
			border-radius: 0;
		}

		.child {
			flex: 1;
			width: 550rpx;
			padding: 0 30rpx;

			.cell {
				flex-direction: row;
				flex-wrap: wrap;
				justify-content: space-between;
				padding: 8rpx 0;

				.item {
					width: 230rpx;
					height: 76rpx;
					margin: 8rpx 0;
					padding: 0 30rpx;
				}
			}
		}
	}

	/* 扩展消息界面 */
	.skeleton-message {
		.hd {
			flex-direction: row;
			align-items: center;
			justify-content: space-around;
			margin: 60rpx 0 50rpx;

			.item {
				width: 100rpx;
				height: 100rpx;
				border-radius: 20rpx;
				background: rgba(40, 120, 255, 0.06);
			}
		}

		.bd {
			padding: 0 34rpx;

			.item {
				flex-direction: row;
				align-items: center;
				margin: 40rpx 0;

				.head {
					width: 100rpx;
					height: 100rpx;
					margin-right: 14rpx;
					background: rgba(40, 120, 255, 0.06);
					border-radius: 50rpx;
				}

				.list {
					flex: 1;

					.t {
						flex-direction: row;
						justify-content: space-between;

						.name {
							width: 132rpx;
							height: 38rpx;
							background: rgba(40, 120, 255, 0.06);
							border-radius: 6rpx;
						}

						.time {
							width: 195rpx;
							height: 20rpx;
							background: rgba(40, 120, 255, 0.06);
							border-radius: 6rpx;
						}
					}

					.b {
						margin-top: 26rpx;

						.text {
							width: 464rpx;
							height: 26rpx;
							background: rgba(40, 120, 255, 0.06);
							border-radius: 6rpx;
						}
					}
				}
			}
		}
	}

	/* 扩展模板news样式 */
	.ls_news {
		flex: 1;
		margin-left: 20rpx;
	}

	.ls_news_img {
		width: 240rpx;
		height: 200rpx;
		margin-bottom: 30rpx;
	}

	.ls_news_user {
		height: 32rpx;
		margin-bottom: 30rpx;
		width: 260rpx;
	}

	.ls_news_time {
		height: 32rpx;
		margin-bottom: 30rpx;
		width: 130rpx;
	}
</style>
